home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-05 | 43.0 KB | 1,145 lines |
- *-------------------------------------------------------------------------------
- *-- Program...: DATES.PRG
- *-- Programmer: Ken Mayer (CIS: 71333,1033)
- *-- Date......: 06/25/1992
- *-- Notes.....: These are the date functions/procedures I felt were not as
- *-- commonly used as those left behind in PROC.PRG. See README.TXT
- *-- for details on the use of this library file.
- *-------------------------------------------------------------------------------
-
- FUNCTION DateText3
- *-------------------------------------------------------------------------------
- *-- Programmer..: Miriam Liskin
- *-- Date........: 03/02/1992
- *-- Notes.......: Display date in format Month, year
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 05/21/1991 - original function.
- *-- 03/02/1992 - This one's Douglas P. Saine's (XRED) invention.
- *-- In his words: "I just removed the middle part looking for
- *-- the day. For the things I do, I only need the month and
- *-- year. (I work for a defense contracter, accuracy of dates
- *-- has never been of great concern. <G>)"
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: DateText3(<dDate>)
- *-- Example.....: ? DateText3(date())
- *-- Returns.....: July, 1991
- *-- Parameters..: dDate = date to be converted
- *-------------------------------------------------------------------------------
-
- parameters dDate
-
- RETURN cmonth(dDate)+", "+str(year(dDate),4)
- *-- EoF: DateText3()
-
- FUNCTION Age2
- *-------------------------------------------------------------------------------
- *-- Programmer..: Martin Leon (HMAN)
- *-- Date........: 04/22/1992
- *-- Notes.......: Returns number of full years between two dates, which is
- *-- age of a person born on the first date as of the second.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 10/23/1991 - original function.
- *-- 04/22/1992 -- Description modified, parameters changed by
- *-- Jay Parsons (CIS: 70160,340).
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Age2(<d1>,<d2>)
- *-- Example.....: ? "Joe was "+ltrim(str(age2(dBDay,{10/16/85})))+;
- *-- " on the day of ..."
- *-- Returns.....: Numeric value in years
- *-- Parameters..: d1 = first date, such as date of birth
- *-- d2 = second date, when age is wanted
- *-------------------------------------------------------------------------------
-
- parameters d1, d2
- private nYears
-
- nYears = year(d2) - year(d1)
- do case
- case month(d1) > month(d2)
- nYears = nYears - 1
- case month(d1) = month(d2)
- if day(d1) > day(d2)
- nYears = nYears - 1
- endif
- endcase
-
- RETURN nYears
- *-- EoF: Age2()
-
- FUNCTION IsLeap
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 01/13/1992
- *-- Notes.......: Is the year given a Leap Year? Year given must be after 1500
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/08/1991 - original function.
- *-- 01/13/1992 -- updated to handle two digit OR four digit year.
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: IsLeap(<nYear>)
- *-- Example.....: IsLeap(91)
- *-- Returns.....: Logical (.t./.f.)
- *-- Parameters..: nYear = Numeric form of year -- last two digits (i.e., 91),
- *-- or all four digits (i.e., 1991)
- *-------------------------------------------------------------------------------
-
- parameter nYear
- private lReturn
-
- *-- deal with two digit year ...
- if nYear < 100
- nYear = nYear + 100 * int(year(date())/100)
- endif
-
- lReturn = mod(iif(mod(nYear,100)=0,nYear/100,nYear),4)=0
-
- RETURN lReturn
- *-- EoF: IsLeap()
-
- FUNCTION Annivrsry
- *-------------------------------------------------------------------------------
- *-- Programmer..: David Love (CIS: 70153,2433) and Jay Parsons (CIS: 70160,340)
- *-- Date........: 11/10/1991
- *-- Notes.......: Checks to see if an anniversary date falls within a range of
- *-- dates (handy for mailings for organizations, checking to see
- *-- if someone's birthday falls within certain dates, etc.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: AGE2() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: Annivrsry(<dTest>,<dBegin>,<dEnd>)
- *-- Example.....: if Annivrsry(dBDay,{03/01/91},{03/31/91})
- *-- *-- do something
- *-- endif
- *-- Returns.....: .t. if a date (dTest) falls within the period beginning at
- *-- dBegin or ending at dEnd, inclusive. .F. for any other
- *-- occurance, including invalid ranges or blank dates.
- *-- Parameters..: dTest = Date being tested for ...
- *-- dBegin = Beginning of range
- *-- dEnd = End of range
- *-------------------------------------------------------------------------------
-
- parameters dTest, dBegin, dEnd
- private nYears
-
- nYears = 0
- if dBegin <= dEnd .AND. dTest <= dEnd && will be false if blank
- nYears = age2(dTest,dEnd) - iif(dTest < dBegin,age2(dTest,dBegin-1),0)
- endif
-
- RETURN nYears > 0
- *-- EoF: Annivrsry()
-
- FUNCTION AddMonths
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 11/10/1991
- *-- Notes.......: Finds same day as given date N months ahead.
- *-- This function will return the first day of the following
- *-- month if there is no date in the month otherwise returned
- *-- and nMonths is positive, or the last day of the month if
- *-- nMonths is negative. That is, a call with {01/31/91}
- *-- (January 31, 1991) and 1 would yield March 1, there being
- *-- no February 31.
- *-- Do not use this function successively to find first the
- *-- date one month ahead, then the date one month beyond that.
- *-- Instead, to find the date two months ahead from the original
- *-- date, call this function with the original date and
- *-- nMonths = 2. Otherwise, in the example, you'll get April 1
- *-- the second time rather than the correct March 31.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: AddMonths(<dDate>,<nMonths>)
- *-- Example.....: ?AddMonths({01/01/91},1)
- *-- Returns.....: Date
- *-- Parameters..: dDate = Date being tested for ...
- *-- dMonths = Number of months "ahead"
- *-------------------------------------------------------------------------------
-
- parameters dDate, nMonths
- private dNew, dTest,dReturn
-
- dNew = dDate - day(dDate)+ 15 + 30.436875 * nMonths && middle of month
- dTest = dNew - day(dNew) + day(dDate)
- dReturn = iif(month(dTest) = month(dNew),dTest, ;
- dTest - day(dTest) + iif(nMonths > 0, 1, 0))
-
- RETURN dReturn
- *-- EoF: AddMonths()
-
- FUNCTION AddYears
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 11/14/1991
- *-- Notes.......: Finds same day as given date N years ahead.
- *-- Using this function dBASE IV will take care of converting
- *-- February 29 to March 1 if moving from a leap to a non-leap
- *-- year. However, neither may be used backwards (negative
- *-- value of nYears) since the date a year before February 29,
- *-- 1992 will be returned as March 1, 1991, not February 28, 1991.
- *-- If you must move back, either check explicitly for February 29
- *-- as the original date or add code as in the addmonths()
- *-- function to test for the date returned being of a different
- *-- month than the original and, if it is, to subtract its day().
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - original function.
- *-- 11/14/1991 - Ken Mayer - expanded out to make it easier
- *-- to read, and see what's happening.
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: AddYears(<dDate>,<nYears>)
- *-- Example.....: ?AddYears({01/01/91},1)
- *-- Returns.....: Date
- *-- Parameters..: dDate = Date being tested for ...
- *-- dYears = Number of Years "ahead"
- *-------------------------------------------------------------------------------
-
- parameters dDate, nYears
- private cYear,cMonth,cDay,dReturn
-
- cYear = str(year(dDate) + nYears)
- cMonth = right(str(month(dDate) + 100),2)
- cDay = right(str(day(dDate) + 100),2)
- dReturn = ctod(cMonth+"/"+cDay+"/"+cYear)
-
- RETURN dReturn
- *-- EoF: AddYears()
-
- FUNCTION DoY
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 11/14/1991
- *-- Notes.......: Returns the day of the year of a date (from beginning of the
- *-- year).
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - original function.
- *-- 11/14/1991 - Ken Mayer - expanded for readability ...
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: DoY(<dDate>)
- *-- Example.....: ?DoY({01/01/91})
- *-- Returns.....: Numeric value of day of year
- *-- Parameters..: dDate = Date being tested for ...
- *-------------------------------------------------------------------------------
-
- parameters dDate
- private cYear,dStart,nReturn
-
- cYear = right(str(year(dDate)),2)
- dStart = ctod("01/01/"+cYear)
- nReturn = dDate+1 - dStart
-
- RETURN nReturn
- *-- EoF: DoY()
-
- FUNCTION WeekNo
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 11/14/1991
- *-- Notes.......: Returns the week number of the year of a date (from beginning
- *-- of the year).
- *-- To use this function but start the week on a different day,
- *-- change the 1 in the second-to-last line, the dow() of Sunday,
- *-- to the dow() of the day that should start each week, 2 for
- *-- Monday through 7 for Saturday.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/10/1991 - original function.
- *-- 11/14/91 - Ken Mayer - expanded for readability ...
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: WeekNo(<dDate>)
- *-- Example.....: ?WeekNo({01/01/91})
- *-- Returns.....: Numeric value of week number
- *-- Parameters..: dDate = Date being tested for ...
- *-------------------------------------------------------------------------------
-
- parameters dDate
- private dBaseDate,nReturn
-
- dBaseDate = dDate - doy(dDate)
- dBaseDate = dBaseDate - mod(dow(dBaseDate - 1), 7)
- nReturn = int((dDate - dBaseDate) / 7)
-
- RETURN nReturn
- *-- EoF: WeekNo()
-
- FUNCTION Holiday
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 04/22/1992
- *-- Notes.......: Returns the date of a specific "floating" holiday (using
- *-- chart below) for current year.
- *-- Name Code
- *-- President's Day P
- *-- Daylight saving time D
- *-- Memorial Day M
- *-- Labor Day L
- *-- Columbus Day C
- *-- Resume Standard time S
- *-- Election Day E
- *-- Thanksgiving T
- *-- Advent (1st Sunday) A
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/01/1991 - original function.
- *-- 11/15/1991 - Ken Mayer - takes a code and year -- I basically
- *-- simplified the use of the function.
- *-- 04/22/1992 - Jay Parsons - added 'D' and 'S' options
- *-- (daylight saving time and return to standard)
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Holiday(<nYear>,"<cCode>")
- *-- Example.....: ? Holiday(92,"P") && date of President's day, 1992
- *-- Returns.....: Date of specified holiday ...
- *-- Parameters..: nYear = Year you need the holiday date for ...
- *-- cCode = one of the codes above for specific holiday
- *-------------------------------------------------------------------------------
-
- parameters nYear,cCode
- private dBaseDate,cCode,cYear,nDoW,cFirst,dReturn
-
- cCode = upper(cCode)
- cYear = ltrim(str(nYear))
- do case
- case cCode = "P" && President's day (3rd Mon of Feb)
- cFirst = "02/15/"
- nDoW = 2
- case cCode = "D" && Daylight time U.S. (1st Sun of April)
- cFirst = "04/01/"
- nDoW = 1
- case cCode = "M" && Memorial day (last Mon of May)
- cFirst = "05/25/"
- nDoW = 2
- case cCode = "L" && Labor day (1st Mon of Sep)
- cFirst = "09/01/"
- nDoW = 2
- case cCode = "C" && Columbus Day (2nd Mon of Oct)
- cFirst = "10/08/"
- nDoW = 2
- case cCode = "S" && Standard Time U.S. (Last Sun of Oct)
- cFirst = "10/25/"
- nDoW = 1
- case cCode = "E" && Election Day (1st Tues of Nov not Nov 1)
- cFirst = "11/02/"
- nDoW = 3
- case cCode = "T" && Thanksgiving (fourth Thursday of Nov)
- cFirst = "11/22/"
- nDoW = 5
- case cCode = "A" && 1st Sun of Advent (Sunday closest Nov 30)
- cFirst = "11/27/"
- nDoW = 1
- otherwise
- return {} && if not one of above, return blank date ...
- endcase
- dFirst = ctod(cFirst + cYear)
- dBaseDate = dFirst + 7 - nDow
- dReturn = dBaseDate - dow( dBaseDate ) + nDow && dow( dBaseDate )
-
- RETURN dReturn
- *-- EoF: Holiday()
-
- FUNCTION EasterDay
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (USSBBS, CIS 70160,340)
- *-- Date........: 12/03/1992
- *-- Notes.......: Returns date of Easter for given year after 1582.
- *-- This gives the date of Easter as celebrated by Western
- *-- churches. The algorithm is from Example 1.3.2.14 of
- *-- Volume I of "The Art of Computer Programming", 2nd
- *-- Edition, Addison-Wesley, Reading, MA, 1973, by Donald
- *-- Knuth, who attributes it to Aloysius Lilius of Naples
- *-- and Christopher Clavius of Germany, both floruit 1582.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 11/18/1991 - original function.
- *-- 04/22/1992 - Jay Parsons - Notes expanded.
- *-- 11/20/1992 - David Love - Added the private variable lYear
- *-- 12/03/1992 - Jay Parsons - renamed lYear to nYr, dPascMoon
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: EasterDay(<Year>)
- *-- Example.....: EasterDay(91)
- *-- Returns.....: Date (in dBASE date format) of Easter
- *-- Parameters..: nYear = Numeric form of year - YYYY or YY format
- *-------------------------------------------------------------------------------
-
- parameters nYear
- private nYr,nGolden,nCentury,nNoLeap,nMoonOrbit,nEPact,dPascMoon,dReturn
-
- *-- deal with two digit year ...
- nYr = nYear
- if nYr < 100
- nYr = nYr + 100 * int(year(date())/100)
- endif
-
- nGolden = 1+mod(nYr,19)
- nCentury = floor(nYr/100)+1
- nNoLeap = floor(3*nCentury/4)-12
- nMoonOrbit = floor((8*nCentury+5)/25)-5
- nEPact = mod(11*nGolden+nMoonOrbit-nNoLeap+20,30)
- nEPact = nEPact+iif(nEPact=24.or.(nEPact=25.and.nGolden>11),1,0)
- dPascMoon = ctod("03/21/"+str(nYr)+mod(53-nEPact,30))
- dReturn = dPascMoon+8-dow(dPascMoon)
-
- RETURN dReturn
- *-- EoF: EasterDay()
-
- FUNCTION nDoW
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 04/22/1992
- *-- Notes.......: Numeric Day of Week -- returns the numeric value of the
- *-- day of week for use by some of the other date functions
- *-- below.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 02/25/1992 - original function.
- *-- 04/22/1992 - Jay Parsons - modified example/descriptions,
- *-- added ltrim() of argument.
- *-- Calls.......: None
- *-- Called by...: None
- *-- Usage.......: nDoW(<cDay>)
- *-- Example.....: nDay = nDoW("Tues")
- *-- Returns.....: Numeric dow value of day of week given
- *-- Parameters..: cDay -- Character memvar containing "day" of week ('MONDAY',
- *-- etc ...)
- *-------------------------------------------------------------------------------
-
- parameter cDay
-
- RETURN at(upper(left(ltrim(cDay),3))," SUN MON TUE WED THU FRI SAT")/4
- *-- nDoW()
-
- FUNCTION FWDoM
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 02/25/1992
- *-- Notes.......: First Working Day of the Month -- originally I used Dan
- *-- Madoni's stuff from Technotes, but Jay came along and pointed
- *-- out an easier way to do this. SO, here we have a shorter,
- *-- faster, FWDoM function. This returns the first WORKING
- *-- day of the month.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: FWDoM(<dDate>)
- *-- Example.....: ? CDoW( FWDoM(DATE()) ) (character day of week ...)
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-------------------------------------------------------------------------------
-
- parameters dDate
- private dReturn, nDay
-
- dReturn = dDate - day(dDate) + 1
- nDay = DoW(dReturn)
-
- RETURN dReturn + iif(nDay=7,2,iif(nDow=1,1,0))
- *-- EoF: FWDoM()
-
- FUNCTION LWDoM
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 02/25/1992
- *-- Notes.......: Last Working Day of the Month -- function from Jay (new
- *-- version like FWDoM) to return the last working day of the
- *-- month. Give a date, the function returns the last WORKING day
- *-- of the month. This has a companion function, giving the
- *-- FIRST working day (see above).
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: LDOM() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: LWDoM(<dDate>)
- *-- Example.....: ? LWDoM(DATE())
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-------------------------------------------------------------------------------
-
- parameters dDate
- private dReturn, nDay
-
- dReturn = ldom(dDate)
- nDay = DoW(dReturn)
-
- RETURN dReturn - iif(nDay=7,1,iif(nDay=1,2,0))
- *-- EoF: LWDoM()
-
- FUNCTION FDoD
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 02/25/1992
- *-- Notes.......: First Day of Date. This function works to give the first
- *-- date in a given month (using a date) that a specific day
- *-- of the week occurs (i.e., first Monday of the month).
- *-- It returns a blank date if the day of week doesn't match,
- *-- but is not case sensitive. New, slimmer, sleeker version
- *-- by Jay ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: NDOW() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: FDoD(<dDate>,"<cDay>")
- *-- Example.....: ? FDoD(DATE(),"Tuesday")
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-- cDay -- Day of week to look for ...
- *-------------------------------------------------------------------------------
-
- parameters dDate, cDay
- private dReturn, nDay
-
- nDay = nDoW(cDay)
- dReturn = dDate - day(dDate) + 1
-
- RETURN dReturn + mod(nDay+7 - DoW(dReturn),7)
- *-- EoF: FDoD()
-
- FUNCTION LDoD
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 02/25/1992
- *-- Notes.......: Last Day of Date. This function works to give the last
- *-- date in a given month (using a date) that a specific day
- *-- of the week occurs (i.e., last Monday of the month).
- *-- It returns a blank date if the day of week doesn't match,
- *-- but is not case sensitive. New version as FDoD() ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: LDOM() Function in DATES.PRG
- *-- NDOW() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: LDoD(<dDate>,"<cDay>")
- *-- Example.....: ? LDoD(DATE(),"Tuesday")
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-- cDay -- Day of week to look for ...
- *-------------------------------------------------------------------------------
-
- parameters dDate, cDay
- private dReturn
-
- nDay = nDoW(cDay)
- dReturn = ldom(dDate)
-
- RETURN dReturn - mod(dow(dReturn) + 7 - nDay,7)
- *-- EoF: LDoD()
-
- FUNCTION LDoM
- *-------------------------------------------------------------------------------
- *-- Programmer..: Ken Chan (HazMatZak)
- *-- Date........: 02/26/1992
- *-- Notes.......: Last Day of Month -- Zak wrote this one up as a MUCH shorter
- *-- and more straightforward version of the one I did. >sigh<.
- *-- This function returns the date of the last day of the month.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: LDoM(<dDate>)
- *-- Example.....: ? LDoM(DATE())
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-------------------------------------------------------------------------------
-
- parameter dDate
- private dNxtMonth
-
- dNxtMonth = dDate - day(dDate) + 45 && middle of next month
-
- RETURN dNxtMonth - day(dNxtMonth)
- *-- EoF: LDoM()
-
- FUNCTION NumDoD
- *-------------------------------------------------------------------------------
- *-- Programmer..: Ken Mayer (CIS: 71333,1033)
- *-- Date........: 02/24/1992
- *-- Notes.......: This function will return the x daytype of a month.
- *-- Example: what if you need the third Monday of the month?
- *- Send to this function a date (any date) of the month,
- *-- the number you need (first, second...) and the day you
- *-- need. The function is not case specific.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: FDOD() Function in DATES.PRG
- *-- NDOW() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: NumDoD(<dDate>,<nDay>,<cDay>)
- *-- Example.....: ?NumDoD({02/03/92},3,"Monday")
- *-- Returns.....: Date
- *-- Parameters..: dDate = Any date of the month (and year) needed
- *-- nDay = Number of day you need (i.e., third cDay of month)
- *-- cDay = Character value of day (Monday, Tuesday, etc.)
- *-------------------------------------------------------------------------------
-
- parameter dDate, nDay, cDay
- private dReturn
-
- dReturn = FDoD(dDate,cDay) && get the first day of this type of the month
- if nDay > 1 && if it's greater than one, add 7 (1 week) for
- && required # ...
- dReturn = dReturn + ((nDay-1)*7)
- endif
-
- RETURN dReturn
- *-- EoF: NumDoD()
-
- FUNCTION WDiF
- *-------------------------------------------------------------------------------
- *-- Programmer..: Martin Leon (HMAN)
- *-- Date........: 12/12/1991
- *-- Notes.......: This UDF is designed to return the first Working Day In the
- *-- Future of a specific date, based on a # of days. For example,
- *-- to return the first working day, 10 days from the current
- *-- date, you can pass the parameters of DATE() and 10. If the
- *-- date 10 days from today is a working day, that date is
- *-- returned, otherwise, the function returns the next closest
- *-- working day. You may, if you wish, use a database to
- *-- store holidays. If you do, the database must be laid out
- *-- with the following structure:
- *-- HOLIDAYS.DBF
- *-- Field name Field type MDX?
- *-- HOLIDATE Date Y
- *-- Once the UDF has been run, the database is left open in
- *-- whatever work area it was opened. If another database was
- *-- in use at the time of calling the UDF, it becomes the active
- *-- database after the UDF is done. The reason for leaving the
- *-- database open is that this speeds up the process when you
- *-- call on the UDF several times in a row.
- *-- To ensure that holidays are working properly, there are
- *-- 3 assumptions made by this function, and all must be true.
- *-- These are: 1) WDIF() assumes that your holidays database
- *-- has an index tag on the HOLIDATE field, 2) there are no
- *-- duplicate entries, and 3) none of the holidays in the data-
- *-- base fall on a weekend date. A simple method for insuring
- *-- the last is:
- *-- USE Holidays
- *-- DELETE FOR DOW( Holidate ) = 7 .or. DOW( Holidate ) = 1
- *-- PACK
- *-- If you do not have a Holidays database, this function will
- *-- work fine ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: WDIF(<dStart>,<nDays>)
- *-- Example.....: ?WDiF(date(),10)
- *-- Returns.....: dBASE date
- *-- Parameters..: dStart = Date to start counting from
- *-- nDays = Number of working days in the future ...
- *-------------------------------------------------------------------------------
-
- parameter dStart, nWDays
- private nweeks, n, nXtraDays, nHDays, dReturn, cNear, cAlias, dTemp
-
- store 0 to nweeks, n, nHDays, nXtraDays
- store {} to dReturn, dTemp
- store "" to cNear, cAlias
- cNear = set("NEAR")
-
- if nWDays = 0
- RETURN 0
- endif
-
- if type("dStart") + type("nWDays") # "DN"
- RETURN -1
- endif
-
- *-- Rough guestimate of future date within a week
- nweeks = int( nWDays / 5 )
- dReturn = dStart + (nweeks * 7)
-
- *-- Left over number of days from integer division above
- nXtraDays = mod( nWDays, 5 )
-
- *-- Check to see if Holidays database is already in use. This is
- *-- done so that we don't have to close and open the database for
- *-- every call to this UDF. The first call opens it and subsequent
- *-- calls select it as needed.
-
- *-- Check all work areas for holidays database, starting with work
- *-- area 10 since this is most likely where it was opened the
- *-- first time.
- n = 10
- do while .not. "HOLIDAYS" $ alias( n )
- n = n - 1
- if n = 0
- exit
- endif
- enddo
- *-- If it is open, store current alias name and select holidays
- *-- database.
- if n # 0
- cAlias = alias()
- select (alias(n))
- else
- *-- If it isn't the currently selected database,
- *-- make sure it exists and use it and select it.
- if file( "HOLIDAYS.DBF" )
- cAlias = alias()
- use Holidays order Holidate in select()
- select Holidays
- endif
- endif
- *-- If it's active now ...
- if alias() = "HOLIDAYS"
- *-- make sure it's in Holidate order, and ...
- if order() # "HOLIDATE"
- set order to Holidate
- endif
- set near on
- *-- count all records in holiday database that fall within the
- *-- range of the starting date and the rough guestimate date.
- seek dStart
- *-- don't count starting day if it's in Holidays database.
- if dStart = Holidate
- skip
- endif
- scan while dReturn >= Holidate
- nHDays = nHDays + 1
- endscan
- set near off
- endif
-
- *-- Add holidays to "left over" days from original guestimate
- nXtraDays = nXtraDays + nHDays
-
- *-- Add extra days one day at a time to the original guestimate,
- *-- skipping over holidays and weekends.
-
- do while nXtraDays > 0
- dReturn = dReturn + 1
- if alias() = "HOLIDAYS"
- if seek(dReturn)
- loop
- endif
- endif
- if dow( dReturn ) = 7 .or. dow( dReturn ) = 1
- loop
- endif
- nXtraDays = nXtraDays - 1
- enddo
-
- *-- If return date falls on Saturday or Sunday, "re-wind" to Friday.
- dReturn = dReturn - ;
- iif( dow( dReturn ) = 7, 1, iif( dow(dReturn) = 1, 2, 0 ))
-
- *-- If another database was origally in use, make it the active
- *-- database again.
- if "" # cAlias
- select (cAlias)
- endif
- *-- set NEAR back to what it was orginally.
- set near &cNear
-
- RETURN dReturn
- *-- EoF: WDiF()
-
- FUNCTION StoD
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 11/10/91
- *-- Notes.......: Convert string YYYYMMDD or YYMMDD to a date regardless of
- *-- SET DATE.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: StoD("<cString>")
- *-- Example.....: ?StoD("19910101")
- *-- Returns.....: Date
- *-- Parameters..: <cString> = Date string you wish converted to "normal" dBASE
- *-- date. Must be in either YYYYMMDD or YYMMDD format.
- *-------------------------------------------------------------------------------
-
- parameters cString
- private dTest, cMonth, cDay, cYear, dReturn
-
- dTest = ctod("01/02/03")
- if len(cString) < 8
- cString = left(str(year(date()),4),2) + cString
- endif
- cYear = left(cString, 4)
- cMonth = substr(cString, 5, 2)
- cDay = right(cString, 2)
- do case
- case month(dTest) = 1
- dReturn = ctod(cMonth + "/" + cDay + "/" + cYear)
- case day(dTest) = 1
- dReturn = ctod(cDay + "/" + cMonth + "/" + cYear)
- otherwise
- dReturn = ctod(cYear + "/" + cMonth + "/" + cDay)
- endcase
-
- RETURN dReturn
- *-- EoF: StoD()
-
- FUNCTION Quarter
- *-------------------------------------------------------------------------------
- *-- Programmer..: Bowen Moursund (CIS: 76566,1405)
- *-- Date........: 02/03/1992
- *-- Notes.......: Returns the quarter of the year of a specific date ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Quarter(<dDate>)
- *-- Example.....: ?Quarter({05/25/1992})
- *-- Returns.....: Numeric (integer) value from 1 to 4 (or 0 on error ...)
- *-- Parameters..: dDate = date to be checked
- *-------------------------------------------------------------------------------
-
- Parameter dDate
-
- RETURN iif(type("dDate")="D",ceiling(month(dDate)/3),0)
- *-- EoF: Quarter()
-
- FUNCTION Dat2Jul
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 03/01/92
- *-- Notes.......: Converts dBASE date to Julian # of days (from January 1,
- *-- 3713 B.C.)
- *-- Rev. History: None
- *-- Written for.: dBASE IV
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Dat2Jul("<dDate>")
- *-- Example.....: ?Dat2Jul(date())
- *-- Returns.....: Numeric
- *-- Parameters..: dDate = Date to convert to Julian ...
- *-------------------------------------------------------------------------------
-
- PARAMETERS dDate
-
- RETURN 2415386 + dDate - ctod( "01/01/01" )
- *-- EoF: Dat2Jul()
-
- FUNCTION Jul2Dat
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 03/01/92
- *-- Notes.......: Converts Julian # of days to dBASE Date
- *-- Rev. History: None
- *-- Written for.: dBASE IV
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Jul2Dat(nJulian)
- *-- Example.....: ?Jul2Dat(2448691)
- *-- Returns.....: Date
- *-- Parameters..: nJulian = Julian date to convert to dBase Date
- *-------------------------------------------------------------------------------
-
- parameters nJulian
-
- RETURN ctod( "01/01/01" ) + (nJulian - 2415386)
- *-- EoF: Jul2Dat()
-
- FUNCTION DateSet
- *-------------------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 70160,340)
- *-- Date........: 03/01/92
- *-- Notes.......: Returns string giving name of current DATE format
- *-- This is not needed in Version 1.5, in which set("DATE")
- *-- returns the format. Unlike that function in 1.5, this
- *-- one cannot distinguish between date formats set with
- *-- different terms that amount to the same thing:
- *-- DMY = BRITISH = FRENCH
- *-- MDY = AMERICAN
- *-- YMD = JAPAN
- *-- If your users will be using one of these formats and
- *-- are sensitive about the name, substitute the one they
- *-- want for the equivalent in this function.
- *-- Rev. History: None
- *-- Written for.: dBASE IV, versions below 1.5
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: DateSet()
- *-- Example.....: ?DateSet()
- *-- Returns.....: Character
- *-- Parameters..: None
- *-------------------------------------------------------------------------------
-
- private cCent, cTestdate, cDelimiter
- cCent = set( "CENTURY" )
- set century off
- cTestdate = ctod( "01/02/03" )
- cDelimiter = substr( dtoc( cTestdate ), 3, 1 )
- set century &cCent
- do case
- case month( cTestdate ) = 1
- RETURN iif( cDelimiter = "-", "USA", "MDY" )
- case day( cTestdate ) = 1
- RETURN iif( cDelimiter = "/", "DMY", ;
- iif( cDelimiter = ".", "GERMAN", "ITALIAN" ) )
- otherwise
- RETURN iif( cDelimiter = ".", "ANSI", "YMD" )
- endcase
-
- *-- EoF: DateSet()
-
- FUNCTION FrstNxtMth
- *-------------------------------------------------------------------------------
- *-- Programmer..: Todd Barry (TODDBARRY)
- *-- Date........: 04/04/1992
- *-- Notes.......: Returns first day of next month
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: FrstNxtMth(<dDate>)
- *-- Example.....: FrstNxtMth( dDate )
- *-- Returns.....: dBASE Date
- *-- Parameters..: dDate -- date to work from ...
- *-------------------------------------------------------------------------------
-
- parameters dDate
- private nYear, nMonth
-
- nYear = year( dDate )
- nMonth = month( dDate )
-
- * return same if blank
- if nYear = 0
- RETURN dDate
- endif
-
- if nMonth < 12
- * all months except December
- nMonth = nMonth + 1
- else
- * December
- nMonth = 1
- nYear = nYear + 1
- endif
-
- RETURN ctod( str( nMonth ) + "/" + "01" + "/" + str( nYear ) )
- *-- EoF: FrstNxtMth()
-
- FUNCTION FDoM
- *-------------------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 71542,2712)
- *-- Date........: 01/05/1993
- *-- Notes.......: First Day of Month
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: FDoM(<dArg>)
- *-- Example.....: ?FDOM(date())
- *-- Returns.....: Date
- *-- Parameters..: dArg = a Date argument -- function returns first day of the
- *-- month of this date.
- *-------------------------------------------------------------------------------
-
- parameter dArg
-
- RETURN dArg - day( dArg ) + 1
- *-- EoF: FDoM()
-
- FUNCTION FDoY
- *-------------------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 71542,2712)
- *-- Date........: 01/05/1993
- *-- Notes.......: Returns the January 1 of the year of the date argument passed
- *-- to it.
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: FDoY(<dArg>))
- *-- Example.....: FDoY(DATE())
- *-- Returns.....: January 1 of the year in dArg
- *-- Parameters..: dArg = date data
- *-------------------------------------------------------------------------------
-
- parameter dArg
- private dJan
- dJan = dArg - day( dArg ) + 1 - 28 * ( month( dArg ) - 1 )
-
- RETURN dJan - day( dJan ) + 1
- *-- EoF: FDoY()
-
- FUNCTION LDoY
- *-------------------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 71542,2712)
- *-- Date........: 01/05/1993
- *-- Notes.......: Returns December 31 of year in date argument passed to
- *-- function.
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: None
- *-- Calls.......: LDoM() Function in DATES.PRG
- *-- Called by...: Any
- *-- Usage.......: LDoY(<dArg>)
- *-- Example.....: ?LDoY(Date())
- *-- Returns.....: Last Day of Year
- *-- Parameters..: dArg = Date
- *-------------------------------------------------------------------------------
-
- parameter dArg
- private dDec
- dDec = dArg - day( dArg ) + 28 * ( 13 - month( dArg ))
-
- RETURN LDoM( dDec )
- *-- EoF: LDoY()
-
- FUNCTION QDate
- *-------------------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [Zak] (CIS:71542,2712)
- *-- Date........: 01/05/1993
- *-- Notes.......: Quicken-style dates
- * Works best when BELL is OFF and CONFIRM is ON
- * Works with any SET DATE format
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: 01/05/1993 1.0
- *-- Calls.......: FDoM() Function in DATES.PRG
- *-- LDoM() Function in DATES.PRG
- *-- FDoY() Function in DATES.PRG
- *-- LDoY() Function in DATES.PRG
- *-- Strip() Function in STRINGS.PRG
- *-- Called by...: WHEN clause of GET
- *-- Usage.......: @ ... GET <dArg> ... WHEN QDate( <dArg> ) ....
- *--
- *-- Key Function
- *-- --- --------
- *-- T Today's date
- *-- - or _ Day before
- *-- + or = Day after
- *-- M First day of month | Repeated keypress will
- *-- H Last day of month | give you previous/next
- *-- Y First day of year | month/year
- *-- R Last day of year |
- *-- digit Begin manual date entry
- *--
- *-- Example.....: dFoo = date()
- *-- @ 10,10 get dFoo when QDate( dFoo )
- *-- Returns.....: .T.
- *-- Parameters..: dArg = Date variable/field you're GETting
- *-------------------------------------------------------------------------------
-
- parameter dArg
- private lLoop, nRow, nCol, lConfirmOn, nKey, cLastKey, cSimKey
- lLoop = .t.
- nRow = row()
- nCol = col()
- lConfirmOn = ( set( "CONFIRM" ) = "ON" )
- cLastKey = ""
- cSimKey = ""
-
- *-- Save screen in case of Esc
- save screen to sQDate
-
- *-- Check for skip flag (used when SET CONFIRM is ON)
- if type( "x__QDate" ) # "U"
- release x__QDate
-
- else
- do while lLoop
- *-- Display current date in special color
- @ nRow, nCol say dArg color gb+/n && <-- use your own color ...
- *-- Move cursor to beginning of date
- @ nRow, nCol say ""
- *-- Wait for a keypress
- nKey = inkey( 0 )
- *-- Convert to uppercase; ignore keys with negative INKEY() values
- cKey = upper( chr( max( nKey, 0 )))
-
- do case
- case cKey = "T" && Today
- dArg = date()
- case cKey = "-" .or. cKey = "_" && The day before
- dArg = dArg - 1
- case cKey = "+" .or. cKey = "=" && The day after
- dArg = dArg + 1
- case cKey = "M" && First day of the month
- dArg = FDoM( iif( cLastKey = "M", dArg - 1, dArg))
- case cKey = "H" && Last day of the month
- dArg = LDoM( iif( cLastKey = "H", dArg + 1, dArg))
- case cKey = "Y" && First day of the year
- dArg = FDoY( iif( cLastKey = "Y", dArg - 1, dArg))
- case cKey = "R" && Last day of the year
- dArg = LDoY( iif( cLastKey = "R", dArg + 1, dArg))
- case cKey $ "0123456789" && Digit -- manual date entry
- lLoop = .f.
- *-- Clear entry and start at beginning
- keyboard chr( 25 ) + chr( 26 ) + cKey
- case nKey >= 32 .and. nKey < 127 .or. nKey > 127
- *-- Ignore invalid keys, like letters and symbols
- case nKey = 27 .or. nKey = 17 && Esc or Ctrl-Q
- lLoop = .f.
- *-- Restore screen and quit
- restore screen from sQDate
- keyboard cKey
- otherwise
- lLoop = .f.
- *-- Figure out how to simulate last keypress
- *-- If SET CONFIRM is OFF
- if .not. lConfirmOn
- *-- Go back up to date field
- cSimKey = "{UP}" && Up arrow
- *-- Create flag variable to skip routine
- public x__QDate
- endif
- cSimKey = cSimKey + "{HOME}"
- *-- Recreate keypress
- do case
- case nKey = -400
- cSimKey = cSimKey + "{BACKTAB}"
- otherwise
- cSimKey = cSimKey + cKey
- endcase
- *-- Clear entry and "type in" date without separators
- *-- And simulate last keypress
- keyboard "{HOME}{CTRL-Y}" + ;
- Strip( dtoc( dArg ), left( ltrim( dtoc( {} )), 1)) + cSimKey
- endcase
- *-- Save key just pressed
- cLastKey = cKey
-
- enddo
-
- endif
-
- *-- release the screen from memory before returning
- release screen sQDate
-
- RETURN .t.
- *-- EoF: QDate()
-
- *--------------------------------------------------------------------------
- *-- Strip() is here from STRINGS.PRG to make life a bit easier ...
- *--------------------------------------------------------------------------
-
- FUNCTION Strip
- *-------------------------------------------------------------------------------
- *-- Programmer..: Kenneth Chan [ZAK] (CIS: 71542,2712)
- *-- Date........: 01/05/1993
- *-- Notes.......: Strips out specified character(s) from a string
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: None
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Strip(<cVar>,<cArg>)
- *-- Example.....: ?strip(dtoc(date(),"/")
- *-- Returns.....: Character
- *-- Parameters..: cVar = variable/field to remove character(s) from
- *-- cArg = item to remove from cVar
- *-------------------------------------------------------------------------------
-
- parameter cVar, cArg
- do while cArg $ cVar
- cVar = stuff( cVar, at( cArg, cVar ), 1, "" )
- enddo
-
- RETURN cVar
- *-- EoF: Strip()
-
- *-------------------------------------------------------------------------------
- *-- EoP: DATES.PRG
- *-------------------------------------------------------------------------------